<?php

/**
 * Post-validator pentru formularul de completare a blocurilor si scarilor componente (EmptyBlocListForm)
 */
class EmptyBlocListPostValidator extends sfValidatorSchema
{

    protected function configure($options = array(), $messages = array())
    {
        parent::configure($options, $messages);

        $this->messages['scara_required'] = 'Specificaţi scările componente !';
        $this->messages['bloc_required'] = 'Specificaţi denumirea blocului !';
        $this->messages['blocuri_required'] = 'Nu aţi completat nimic !';
        $this->messages['max_blocuri'] = 'Sistemul permite înregistrarea a cel mult %max% blocuri (aţi completat %count%).';
        $this->messages['max_scara'] = 'Sistemul permite înregistrarea a cel mult %max% scări pentru un bloc (aţi completat %count%).';
    }

    protected function doClean($values)
    {
        // extrag valorile corespunzatoare subform-ului 'list'
        $formValues = $values[EmptyBlocListForm::WRAPPER_NAME];

        if ($formValues === null)
        {
            return $values;
        }

        $errorSchema = new sfValidatorErrorSchema($this);
        // aceasta subschema ('list') se va adauga la schema principala
        $errorSchemaList = new sfValidatorErrorSchema($this);

        // parcurg subform-urile din 'list'
        foreach ($formValues as $key => $value)
        {
            // creez o schema corespunzatoare pt $key; se va atasa la $errorSchemaList
            $errorSchemaLocal = new sfValidatorErrorSchema($this);

            $scaraExists = $this->scaraExists($value[EmptyBlocForm::WRAPPER_NAME], $emptyScara);

            if (strlen($value['name']))
            {
                // denumirea blocului este specificata
                // daca nu exista nicio scara completata
                if (!$scaraExists)
                {
                    // se va adauga la $errorSchemaLocal
                    $errorSchemaScara = new sfValidatorErrorSchema($this);
                    // se va adauga la $errorSchemaScara
                    $errorSchemaScaraFirst = new sfValidatorErrorSchema($this);
                    // se asociaza eroarea cu field-ul 'name'
                    $errorSchemaScaraFirst->addError(new sfValidatorError($this, 'scara_required'), 'name');
                    // se adauga $errorSchemaScaraFirst la $errorSchemaScara
                    $errorSchemaScara->addError($errorSchemaScaraFirst, '0');
                    // se adauga $errorSchemaScara la $errorSchemaLocal
                    $errorSchemaLocal->addError($errorSchemaScara, EmptyBlocForm::WRAPPER_NAME);
                }
                else
                {
                    foreach ($emptyScara as $scaraKey)
                    {
                        unset($formValues[$key][EmptyBlocForm::WRAPPER_NAME][$scaraKey]);
                    }

                    // numarul de scari trebuie sa fie limitat
                    $countScara = count($formValues[$key][EmptyBlocForm::WRAPPER_NAME]);
                    $maxScara = sfConfig::get('mod_apartamente_max_scara');
                    if ($countScara > $maxScara)
                    {
                        $errorSchemaLocal->addError(new sfValidatorError($this, 'max_scara', array('count' => $countScara, 'max' => $maxScara)), 'name');
                    }
                }
            }
            else
            {
                if ($scaraExists)
                {
                    // denumirea blocului nu este specificata, dar exista scari completate
                    $errorSchemaLocal->addError(new sfValidatorError($this, 'bloc_required'), 'name');
                }
                else
                {
                    // nu exista scari comletate; blocul se ignora
                    unset($formValues[$key]);
                }
            }

            if (count($errorSchemaLocal))
            {
                $errorSchemaList->addError($errorSchemaLocal, (string) $key);
            }
        }

        $countBlocuri = count($formValues);
        $maxBlocuri = sfConfig::get('mod_apartamente_max_blocuri');
        // daca nu exista nici un bloc completat
        if ($countBlocuri == 0)
        {
            $errorSchema->addError(new sfValidatorError($this, 'blocuri_required'));
        }
        // daca sunt prea multe blocuri completate
        elseif ($countBlocuri > $maxBlocuri)
        {
            $errorSchema->addError(new sfValidatorError($this, 'max_blocuri', array('count' => $countBlocuri, 'max' => $maxBlocuri)));
        }

        if (count($errorSchemaList))
        {
            $errorSchema->addError($errorSchemaList, EmptyBlocListForm::WRAPPER_NAME);
        }

        if (count($errorSchema))
        {
            throw $errorSchema;
        }

        $values[EmptyBlocListForm::WRAPPER_NAME] = $formValues;

        return $values;
    }

    protected function scaraExists($values, &$emptyScara = array())
    {
        $scaraExists = false;
        $emptyScara = array();
        foreach ($values as $key => $value)
        {
            if (strlen($value['name']))
            {
                $scaraExists = true;
            }
            else
            {
                $emptyScara[] = $key;
            }
        }

        return $scaraExists;
    }

}
